let userDao = require('../dao/userDao');
let safeboxDao = require('../dao/safeboxDao');
let tokenUtil = require('../token');
let smsService = require('./SmsService');
let md5 = require('js-md5');

let assert = require('assert');
let mysqlPool = require('../dao/MySQLPool');

const { BusiError, SysError } = require('../exception/exception');




class SafeBoxService {
    constructor() {
    }

    async get(uid){
        return await safeboxDao.get(uid);
    }

    async new(uid, pwd){
        await mysqlPool.doWithTx(async function (conn) {
            let safeBox = await safeboxDao.getWithTx(conn, uid);
            if (!safeBox) {
                let res = await safeboxDao.newWithTx(conn, uid, md5(pwd));
                assert(res > 0, "save safebox record err: res <= 0");
            } else {
                if (safeBox.pwd) {
                    throw new BusiError(500, "保险箱密码已经存在, 不能再次设置");
                }

                let res = await safeboxDao.updatePwdWithTx(conn, uid, md5(pwd));
                if (res < 1){
                    throw new BusiError(500, "设置密码失败, 请稍后再试");
                }
            }
        });
    }

    async updatePwdWithPrePwd(uid, oldPwd, pwd){
        await mysqlPool.doWithTx(async function (conn) {
            let safeBox = await safeboxDao.getWithTx(conn, uid);
            assert(safeBox, "update safebox pwd err: res <= 0");

            assert(safeBox.pwd === md5(oldPwd), "update safebox pwd err: safeBox.pwd !== md5(oldPwd)");

            let res = await safeboxDao.updatePwdWithTx(conn, {uid: uid, pwd: md5(pwd)});
            assert(res > 0, "update safebox pwd err: res <= 0");
        });
    }

    /**
     *
     * @param dto
     * @param {String} dto.uid
     * @param {String} dto.pwd
     * @param {Number} dto.amt
     * @returns {Promise<{coin: Number, safeboxCoin: (number|*)}>}
     */
    async in(dto) {
        await mysqlPool.doWithTx(async function (conn) {
            let leftCoin = await userDao.getCoinWithTx(conn, dto.uid);
            if (leftCoin < dto.amt){
                throw new BusiError(500, "存入金额不能大于当前账号余额");
            }

            let safeBox = await safeboxDao.getWithTx(conn, dto.uid);
            if (!safeBox || !safeBox.pwd){
                throw new BusiError(500, "保险箱暂未设置密码, 请先设置密码");
            }

            if (!dto.pwd || dto.pwd === ''){
                throw new BusiError(500, "保险箱密码错误, 暂不能存入");
            }

            if (md5(dto.pwd) !== safeBox.pwd){
                throw new BusiError(500, "保险箱密码错误, 暂不能存入");
            }

            let res = await safeboxDao.updateWithTx(conn, {uid: dto.uid, amt: dto.amt});
            if (res < 1) {
                throw new BusiError(500, "存入失败, 请稍后再试");
            }

            res = await userDao.decCoinWithTx(conn, dto.uid, dto.amt);
            if (res < 1) {
                console.logw("dec user coin err: res > 0");
                throw new BusiError(500, "存入失败, 请稍后再试");
            }
        });

        let leftCoin = await userDao.getCoin(dto.uid);
        let safeBox = await safeboxDao.get(dto.uid);

        return {coin:leftCoin, safeboxCoin: safeBox.amt};
    }

    async out(dto) {
        await mysqlPool.doWithTx(async (conn) => {
            let safeBox = await safeboxDao.getWithTx(conn, dto.uid);
            if (!safeBox || !safeBox.pwd){
                throw new BusiError(500, "保险箱暂未设置密码, 请先设置密码");
            }

            if (!dto.pwd || dto.pwd === ''){
                throw new BusiError(500, "保险箱密码错误, 暂不能存入");
            }

            if (md5(dto.pwd) !== safeBox.pwd){
                throw new BusiError(500, "保险箱密码错误, 暂不能取出");
            }

            if (safeBox.amt < dto.amt){
                throw new BusiError(500, "取款金额大于保险箱金额");
            }

            let res = await safeboxDao.updateWithTx(conn, {uid: dto.uid, amt: -dto.amt});
            if (res < 1) {
                throw new BusiError(500, "取出失败, 请稍后再试");
            }
            let res1 = await userDao.incCoinWithTx(conn, dto.uid, dto.amt);
            if (res1 < 1) {
                console.logw("inc user coin err: res1 <= 0");
                throw new BusiError(500, "取出失败, 请稍后再试");
            }
        });

        let leftCoin = await userDao.getCoin(dto.uid);
        let safeBox = await safeboxDao.get(dto.uid);
        return {coin:leftCoin, safeboxCoin: safeBox.amt};
    }

    /**
     *
     * @param {String} uid
     * @param {String} mobile
     * @param {String} pwd
     * @param {String} code
     * @returns {Promise<void>}
     */
    async updatePwdByCode (uid, mobile, pwd, code) {
        let userInfo = await userDao.getUserByMobile(mobile);
        if (!userInfo) {
            throw new BusiError(500, "该用户不存在");
        }

        if (uid !== userInfo.uid) {
            throw new BusiError(500, "非法访问");
        }

        await smsService.validSafeBoxPwdCode(mobile, code);
        console.logw(userInfo.uid, "更新为新密码", pwd);
        await safeboxDao.updatePwd(userInfo.uid, md5(pwd));
    }
}

let safeboxService = new SafeBoxService();
module.exports = safeboxService;